﻿'         This file is Copyright © 2008-2012 Billy O'Neal and Aommaster
'                            All rights reserved.
'
' This file is released under the 2-Clause BSD license, included in LICENSE.TXT
'                           and on the MHWT website
Imports System.ComponentModel
Imports System.Text
Imports System.Runtime.Serialization
Imports System.Text.RegularExpressions

<System.Serializable()> Friend Class Topic : Implements IComparable
    Private GUIDInternal As Guid
    Private UsernameInternal As String = ""
    Private DaysInternal As Date = Date.Now.Date
    Private LinkInternal As String = ""
    Private WithEvents CansInternal As New BindingList(Of SpeechInstance)
    Private StatusInternal As String = "0 day(s)"
    Private NotesInternal As String = ""
    Private LogInternal As String = ""
    Private AdditionalLogsInternal As String = ""
    Private HistoryInternal As String = ""
    Private TotalHistoryInternal As Integer = 0


    Private WithEvents IssuesInternal As New BindingList(Of Issue)
    Public Delegate Sub Generic()
    <System.NonSerialized()> Private dNonSerializableHandlers As New List(Of Generic)
    Private dSerializableHandlers As New List(Of Generic)
    Public Custom Event Deleted As Generic
        AddHandler(ByVal value As Generic)
            If value.Target.GetType.IsSerializable Then
                dSerializableHandlers.Add(value)
            Else
                If dNonSerializableHandlers Is Nothing Then
                    dNonSerializableHandlers = New List(Of Generic)
                End If
                dNonSerializableHandlers.Add(value)
            End If
        End AddHandler
        RemoveHandler(ByVal value As Generic)
            If value.Target.GetType.IsSerializable Then
                dSerializableHandlers.Remove(value)
            Else
                dNonSerializableHandlers.Remove(value)
            End If
        End RemoveHandler
        RaiseEvent()
            Dim temp As New List(Of Generic)
            temp.AddRange(dNonSerializableHandlers)
            For Each item As Generic In temp
                item.Invoke()
            Next
            temp.Clear()
            temp.AddRange(dSerializableHandlers)
            For Each item As Generic In temp
                item.Invoke()
            Next
            temp.Clear()
        End RaiseEvent
    End Event
    <System.NonSerialized()> Private mNonSerializableHandlers As New List(Of Generic)
    Private mSerializableHandlers As New List(Of Generic)
    Public Custom Event Modified As Generic
        AddHandler(ByVal value As Generic)
            If value.Target.GetType.IsSerializable Then
                mSerializableHandlers.Add(value)
            Else
                If mNonSerializableHandlers Is Nothing Then
                    mNonSerializableHandlers = New List(Of Generic)
                End If
                mNonSerializableHandlers.Add(value)
            End If
        End AddHandler
        RemoveHandler(ByVal value As Generic)
            If value.Target.GetType.IsSerializable Then
                mSerializableHandlers.Remove(value)
            Else
                mNonSerializableHandlers.Remove(value)
            End If
        End RemoveHandler
        RaiseEvent()
            Dim temp As New List(Of Generic)
            temp.AddRange(mNonSerializableHandlers)
            For Each item As Generic In temp
                item.Invoke()
            Next
            temp.Clear()
            temp.AddRange(mSerializableHandlers)
            For Each item As Generic In temp
                item.Invoke()
            Next
            temp.Clear()
        End RaiseEvent
    End Event
    Public Sub delete()
        RaiseEvent Deleted()
    End Sub
    Public Sub modify() Handles CansInternal.ListChanged, IssuesInternal.ListChanged

        For Each item As SpeechInstance In CansInternal
            RemoveHandler item.Modified, AddressOf modify
        Next
        For Each item As SpeechInstance In CansInternal
            AddHandler item.Modified, AddressOf modify
        Next
        For Each item As Issue In IssuesInternal
            RemoveHandler item.Modified, AddressOf modify
        Next
        For Each item As Issue In IssuesInternal
            AddHandler item.Modified, AddressOf modify
        Next

        RaiseEvent Modified()
    End Sub
    Public Property Link() As String
        Get
            Return LinkInternal
        End Get
        Set(ByVal value As String)
            If value <> LinkInternal Then
                LinkInternal = value
                RaiseEvent Modified()
            End If
        End Set
    End Property
    Public ReadOnly Property GUID() As Guid
        Get
            Return GUIDInternal
        End Get
    End Property
    Public Property Username() As String
        Get
            Return UsernameInternal
        End Get
        Set(ByVal value As String)
            If value <> UsernameInternal Then
                UsernameInternal = value
                RaiseEvent Modified()
            End If
        End Set
    End Property

    Public Property totalhistory() As Integer
        Get
            Return TotalHistoryInternal
        End Get
        Set(ByVal value As Integer)
            If value <> TotalHistoryInternal Then
                TotalHistoryInternal = value
                RaiseEvent Modified()
            End If
        End Set
    End Property
    Public ReadOnly Property Cans() As BindingList(Of SpeechInstance)
        Get
            Return CansInternal
        End Get
    End Property

    Public Property Status() As String
        Get
            Return StatusInternal
        End Get
        Set(ByVal value As String)
            If value <> StatusInternal Then
                StatusInternal = value
                RaiseEvent Modified()
            End If
        End Set
    End Property
    Public Property Notes() As String
        Get
            Return NotesInternal
        End Get
        Set(ByVal value As String)
            If value <> NotesInternal Then
                NotesInternal = value
                RaiseEvent Modified()
            End If
        End Set
    End Property
    Public Property Log() As String
        Get
            Return LogInternal
        End Get
        Set(ByVal value As String)
            If value <> LogInternal Then
                LogInternal = value
                RaiseEvent Modified()
            End If
        End Set
    End Property
    Public Property History() As String
        Get
            Return HistoryInternal
        End Get
        Set(ByVal value As String)
            If value <> HistoryInternal Then
                HistoryInternal = value
                RaiseEvent Modified()
            End If
        End Set
    End Property

    Public Property Additionallogs() As String
        Get
            Return AdditionalLogsInternal
        End Get
        Set(ByVal value As String)
            If value <> AdditionalLogsInternal Then
                AdditionalLogsInternal = value
                RaiseEvent Modified()
            End If
        End Set
    End Property
    Public ReadOnly Property Issues() As BindingList(Of Issue)
        Get
            Return IssuesInternal
        End Get
    End Property
    Public Property Days() As DateTime
        Get
            Return DaysInternal
        End Get
        Set(ByVal value As DateTime)
            DaysInternal = DateTime.Today.Date
        End Set
    End Property
    Public Overrides Function ToString() As String
        Dim retstring As String = Username
        If CBool(CInt(InStr(Status, "day(s)") <> 0 Or Status = "") Or InStr(Status, "CloseWait")) Then
            Dim now As Date = Date.Now.Date
            Dim number As TimeSpan = now.Subtract(Days)
            Dim val As Integer = number.Days
            If InStr(Status, "CloseWait") = 0 Then
                Status = val.ToString & " day(s)"
            Else
                Status = "CloseWait --> " & val.ToString & " Day(s)"
            End If

        End If
        retstring += " [" + Status + "]"
        Return retstring
    End Function
    Public Sub New()
        GUIDInternal = System.Guid.NewGuid
    End Sub
    <OnDeserialized()> Private Sub OnDeSerialized(ByVal context As StreamingContext)
        dNonSerializableHandlers = New List(Of Generic)
        dSerializableHandlers = New List(Of Generic)
        mNonSerializableHandlers = New List(Of Generic)
        mSerializableHandlers = New List(Of Generic)
        If UsernameInternal Is Nothing Then UsernameInternal = ""
        If LinkInternal Is Nothing Then LinkInternal = ""
        If StatusInternal Is Nothing Then StatusInternal = ""
        If NotesInternal Is Nothing Then NotesInternal = ""
        If LogInternal Is Nothing Then LogInternal = ""
    End Sub
    Function CompareTo(ByVal obj As Object) As Integer Implements IComparable.CompareTo
        If obj.GetType() Is GetType(Topic) Then
            Dim compObj As Topic = DirectCast(obj, Topic)
            If StatusInternal = Nothing Then StatusInternal = New String(CType("", Char()))
            If compObj.StatusInternal = Nothing Then compObj.StatusInternal = New String(CType("", Char()))
            Dim stats As String = Me.StatusInternal
            If stats = "" Then
                stats = "______"
            End If
            Dim stats2 As String = compObj.Status
            If stats2 = "" Then
                stats2 = "______"
            End If
            Return (stats + Username).CompareTo(stats2 + compObj.Username)
        Else
            Throw New System.ArgumentException("Non comparable objects in type ""Topic"".")
        End If
    End Function
    Public Sub browse()
        If LinkInternal <> "" Then
            Try
                'Standard IPB
                Dim temp As String = LinkInternal
                If temp.Contains(".html") Then
                    temp = Regex.Replace(temp, "(.*?)/topic([\d]*).*", "$1/index.php?showtopic=$2")
                End If
                Dim regMatch As Match = Regex.Match(temp, "(?<domain>http://[^?]*)\?.*?topic=(?<topicnum>[\d]+)")
                temp = regMatch.Groups.Item("domain").Value + "?showtopic=" + regMatch.Groups.Item("topicnum").Value + "&view=getlastpost"
                System.Diagnostics.Process.Start(temp)
            Catch ex As Exception
                Try
                    'IPB w/ community SEO module
                    Dim temp As String = LinkInternal
                    Dim regMatch As Match = Regex.Match(temp, "(?<domain>http://(?:[^/]*/)*).*?t(?<topicnum>[\d]+)\.html")
                    temp = regMatch.Groups.Item("domain").Value + "?showtopic=" + regMatch.Groups.Item("topicnum").Value + "&view=getlastpost"
                    System.Diagnostics.Process.Start(temp)
                Catch ex2 As Exception
                    Try
                        'TSF
                        Dim temp As String = Regex.Replace(LinkInternal, "(?<prepender>http://[^/]*/.*/[\d]+.*)(?:-[\d]*)?(?<suffix>\.[^\s#]+)", "${prepender}-new-post${suffix}")
                        System.Diagnostics.Process.Start(temp)
                    Catch ex4 As Exception
                        Try
                            'Unable to parse at all
                            System.Diagnostics.Process.Start(LinkInternal)
                        Catch ex3 As Exception
                            'Unable to start with unparsed string... malformed?
                            MsgBox("Failed to open the web page!!")
                        End Try
                    End Try
                End Try
            End Try
        End If
    End Sub
End Class
